package br.usp.icmc.client.controladores;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

//import br.usp.icmc.registro.server.dao.KeyWordCompostaDAO;
import br.usp.icmc.client.dao.KeyWordDAO;
import br.usp.icmc.client.dao.ServiceDAO;
import br.usp.icmc.client.entidades.KeyWord;
//import br.usp.icmc.registro.server.entidades.KeyWordComposta;
//import br.usp.icmc.registro.server.entidades.KeyWordUnitaria;
import br.usp.icmc.client.entidades.Service;

/********************************************************************************
 * <b> <br> Projeto: Aplicativo Cliente <br><b>
 * 
 * Classe de controle das Palavras-Chaves
 * 
 * @author felipe
 * 
 *******************************************************************************/
public class ControllerKeyWord {
	
	KeyWordDAO keyWordDAO;
	KeyWord keyWord;
	//KeyWordUnitaria palavraFilha;
	//KeyWordComposta palavraPai;
	//KeyWordCompostaDAO keyWordCompostaDAO;
	
	
	/**************************************************************************
	 * Construtor padrão da entidade ControllerKeyWord 
	 *************************************************************************/
	
	public ControllerKeyWord() {
		keyWordDAO = new KeyWordDAO();
		keyWord = new KeyWord();
		//palavraFilha = new KeyWordUnitaria();
		//palavraPai = new KeyWordComposta();
		//keyWordCompostaDAO = new KeyWordCompostaDAO();
	}
	

	/**********************************************************
	 * Adiciona a palavra-chave filha
	 * 
	 * @param kw
	 * 		Palavra-chave a ser adicionada ao sistema
	 * @return
	 * 		Retorna a chave adicionada
	 *********************************************************/
	public KeyWord addKeyWord(String kw){
		
		keyWord.setWord(kw);		
		keyWordDAO.save(keyWord);
		
		return keyWord;
	}
	
	/***********************************************************
	 * Adiciona a palavra-chave pai
	 * 
	 * @param word
	 * 		Palavra-chave a ser adicionada
	 * @return
	 * 		Retorna a palavra adicionada
	 **********************************************************/
	/*public KeyWordComposta addKeyWordPai(String word){
			palavraPai.setWord(word);
			keyWordCompostaDAO.save(palavraPai);
		
		return palavraPai;
	}*/
	
	/***********************************************************************************
	 * Associa a palavra-chave filha a uma palavra-chave pai
	 * 
	 * @param palavraFilha
	 * 				Palavra-chave filha
	 * @param pai
	 * 				Palavra-chave pai
	 * @return
	 * 			Retorna 'true' caso a operação seja realizada com sucesso
	 ***********************************************************************************/
	public boolean associaKeyWord(KeyWord palavraFilha, KeyWord palavraPai){
		
		keyWord = keyWordDAO.load(palavraPai.getIdKeyWord());
		keyWord.getWords().add(palavraFilha);
		keyWordDAO.saveOrUpdate(keyWord);
		return true;
	}
	

	/****************************************************************************
	 * Remove uma palavra-chave do sistema
	 * 
	 * @param idKeyWord
	 * 				Id da palavra-chave a ser removida
	 * @return
	 * 				Retorna 'true' caso a operação seja realizada com sucesso
	 *****************************************************************************/
	public boolean removeKeyWord(Long idKeyWord){
		keyWordDAO.deleteById(idKeyWord);		
		return true;
	}
	
	
	/*****************************************************
	 * Lista todas as palavras-chave
	 * 
	 * @return
	 * 		Retorna uma lista de palavras-chave
	 *****************************************************/
	public List listKeyWord(){
		List words = keyWordDAO.selectAllWord();
		return words;
	}
	

	
	/********************************************************************
	 * Edita uma palavra-chave
	 * 
	 * @param id
	 * 			Id da palavra-chave a ser editada
	 * @param newWord
	 * 			Nova palavra-chave
	 * @return
	 *  		Retorna 'true' caso a operação seja realizada com sucesso
	 *********************************************************************/
	public boolean editWord(Long id, String newWord){
		
		keyWord = keyWordDAO.load(id);
		keyWord.setWord(newWord);
		keyWordDAO.saveOrUpdate(keyWord);
		return true;
	}
	
	public List selectParents(){
		return keyWordDAO.selectParent();
	}
	
	public List selectFilhosDoPai(Long idPai){
		return keyWordDAO.selectLeafByParent(idPai);
	}
	
	   public ArrayList<ArrayList<KeyWord>> gerarCaminhosAteFolha(Long idPai) {
	        ArrayList<ArrayList<KeyWord>> caminhos = new ArrayList<>();
	        ArrayList<ArrayList<KeyWord>> caminhosAux;
	        ArrayList<KeyWord> filhos = (ArrayList<KeyWord>) selectFilhosDoPai(idPai);

	        if (filhos.isEmpty()) {
	            caminhos.add(new ArrayList<KeyWord>());
	        } else {
	            for (KeyWord filho : filhos) {
	                caminhosAux = gerarCaminhosAteFolha(filho.getIdKeyWord());
	                caminhos.addAll(gerarCaminhosAteFolha(filho.getIdKeyWord())); // recursao
	            }
	        }

	        for (ArrayList<KeyWord> caminho : caminhos) {
	        	KeyWord word = keyWordDAO.load(idPai);
	            caminho.add(0, word);
	        }

	        return caminhos;
	    }
	    
	    public ArrayList<ArrayList<KeyWord>> gerarSubCaminhos(ArrayList<KeyWord> caminho){
	        ArrayList<ArrayList<KeyWord>> subCaminhos = new ArrayList<>();
	        
	        for(int i = 0; i < caminho.size(); ++i){
	            subCaminhos.add(new ArrayList<>(caminho.subList(0, i+1)));
	        }
	        
	        return subCaminhos;
	    }
	    
	    public ArrayList<ArrayList<KeyWord>> gerarTodosOsCaminhos(Long idPai){
	        ArrayList<ArrayList<KeyWord>> caminhosAteFolha = gerarCaminhosAteFolha(idPai);
	        ArrayList<ArrayList<KeyWord>> todosCaminhos = new ArrayList<>();
	        ArrayList<ArrayList<KeyWord>> aux;
	        
	        for (ArrayList<KeyWord> caminho : caminhosAteFolha) {
	            aux = gerarSubCaminhos(caminho);
	            for(ArrayList<KeyWord> subCaminho : aux){
	                if(!todosCaminhos.contains(subCaminho)){
	                    todosCaminhos.add(subCaminho);
	                }
	            }
	        }
	        
	        return todosCaminhos;
	    }
	    
	    public void printCaminhos(ArrayList<ArrayList<KeyWord>> caminhos){
	    	List l = keyWordDAO.selectWords();
	        for (ArrayList<KeyWord> caminho : caminhos) {
	            for(KeyWord num : caminho){
	                System.out.print(num.getWord() + "/");
	            }
	            System.out.println("");
	        }
	    }
	
		public boolean removeKeyWord(long id){
			keyWordDAO.deleteById(id);
			return true;
		}
		
	    
	    
	
}
